package tankgame02;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

//坦克活动区域
//为了监听键盘事件，实现 KeyListener 接口
//为了让 MyPanel 不停地重绘子弹，需要将 MyPanel 实现 Runnable 接口，当作一个线程使用
public class MyPanel extends JPanel implements KeyListener, Runnable {
    int enemyTanksNumbers = 6;//敌人坦克的初始数量
    //在类中声明自己的坦克
    HeroTank heroTank = null;
    //分别定义 HeroTank,EnemyTank以及Tank 坦克,放入到Vector集合中
    Vector<HeroTank> heroTanks = new Vector<>();
    Vector<EnemyTank> enemyTanks = new Vector<>();
    Vector<Tank> tanks = new Vector<>();
    //定义Vector集合，用于存放炸弹
    //当子弹击中坦克时，就加入一个Bomb对象到bombs
    Vector<Bomb> bombs = new Vector<>();

    //声明三张爆炸图片，用于显示爆炸效果
    Image image1 = null;
    Image image2 = null;
    Image image3 = null;

    public MyPanel() {
        //初始化自己的坦克位置
        heroTank = new HeroTank(200, 600);
        //添加我方坦克对象
        heroTanks.add(heroTank);
        tanks.add(heroTank);
        //将 tanks 设置给 heroTank
        heroTank.setTanks(tanks);
        //设置自己坦克的速度
        heroTank.setSpeed(10);

        //初始化敌人的坦克
        for (int i = 0; i < enemyTanksNumbers; i++) {
            //创建敌方坦克的初始位置
            EnemyTank enemyTank = new EnemyTank(100 * (i + 1), 200);
            //添加敌方坦克对象
            enemyTanks.add(enemyTank);
            tanks.add(enemyTank);
            //tanks 设置给 enemyTank
            enemyTank.setTanks(tanks);
            //随机设置敌方坦克的初始朝向，0~3
            enemyTank.setDirection((int) (Math.random() * 4));
            //启动敌人坦克线程，让他动起来
            new Thread(enemyTank).start();
        }

        //初始化图片对象
        image1 = Toolkit.getDefaultToolkit().getImage
                (Panel.class.getResource("/img/bomb_1.gif"));
        image2 = Toolkit.getDefaultToolkit().getImage
                (Panel.class.getResource("/img/bomb_2.gif"));
        image3 = Toolkit.getDefaultToolkit().getImage
                (Panel.class.getResource("/img/bomb_3.gif"));
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0, 0, 1200, 900);//填充矩形，默认为黑色
        for (int i = 0; i < heroTanks.size(); i++) {
            //取出我方坦克
            HeroTank heroTank = heroTanks.get(i);
            if (heroTank != null && heroTank.isLive) {
                //画出我方坦克
                drawTank(heroTank.getX(), heroTank.getY(), g, heroTank.getDirection(), 1);//自己的坦克
            }

            //画出 hero 射击的所有子弹，遍历Vector集合
            for (int j = 0; j < heroTank.shots.size(); j++) {
                //取出子弹
                Shot shot = heroTank.shots.get(j);
                if (shot != null && shot.isLive) {
                    g.fillOval(shot.x, shot.y, 6, 6);//绘制
                } else {
                    //从Vector集合中删除
                    heroTank.shots.remove(shot);
                }
            }
        }

        //如果bombs集合中有对象，则画出炸弹爆炸效果
        for (int j = 0; j < bombs.size(); j++) {
            //取出炸弹
            Bomb bomb = bombs.get(j);
            //根据当前这个bomb对象的生命值life去画出对应的图片
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (bomb.life >= 9) {
                g.drawImage(image1, bomb.x, bomb.y, 80, 80, this);
            } else if (bomb.life >= 5) {
                g.drawImage(image2, bomb.x, bomb.y, 80, 80, this);
            } else if (bomb.life >= 1) {
                g.drawImage(image3, bomb.x, bomb.y, 80, 80, this);
            }
            //让炸弹的生命值减少
            bomb.lifeDown();
            //如果bomb的生命值为0，就从bombs集合中删除
            if (bomb.life == 0) {
                bombs.remove(bomb);
            }
        }

        //画出敌人的坦克，遍历Vector集合
        for (int i = 0; i < enemyTanks.size(); i++) {
            //取出坦克
            EnemyTank enemyTank = enemyTanks.get(i);
            //先判断当前坦克是否存活
            if (enemyTank.isLive) {
                drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirection(), 0);
            }

            //画出敌方坦克的所有子弹
            for (int j = 0; j < enemyTank.shots.size(); j++) {
                //取出子弹
                Shot shot = enemyTank.shots.get(j);
                //绘制
                if (shot.isLive) {//isLive==true
                    g.fillOval(shot.x, shot.y, 6, 6);
                } else {
                    //从Vector集合中删除
                    enemyTank.shots.remove(shot);
                }
            }

        }
    }

    /**
     * @param x         坦克炮头盖圆心的 x 坐标
     * @param y         坦克炮头盖圆心的 y 坐标
     * @param g         画笔
     * @param direction 坦克的方向（上下左右）
     * @param type      坦克的类型
     */
    //编写坦克图形方法,封装成方法
    public void drawTank(int x, int y, Graphics g, int direction, int type) {
        //根据不同类型的坦克，设置不同的颜色
        switch (type) {
            case 0://敌人的坦克
                g.setColor(Color.YELLOW);
                break;
            case 1://我们的坦克
                g.setColor(Color.CYAN);
                break;
        }

        /**
         * 根据坦克的方向，来绘制对应的坦克
         * 轮子的长度为 70，宽为 14；主控室的长度为 40，宽为 26；
         * 炮头盖的半径为 13，炮管的长度为 34，宽为 4
         * 以炮头盖的圆心为移动中心
         */
        switch (direction) {
            case 0://方向为上
                g.fill3DRect(x - 27, y - 35, 14, 70, false);//坦克左边的轮子
                g.fill3DRect(x + 13, y - 35, 14, 70, false);//坦克右边的轮子
                g.fill3DRect(x - 13, y - 20, 26, 40, false);//坦克主控室
                g.fillOval(x - 13, y - 13, 26, 26);//坦克炮头盖
                g.fillRect(x - 2, y - 34, 4, 35);//坦克炮管
                break;
            case 1://方向为下
                g.fill3DRect(x - 27, y - 35, 14, 70, false);//坦克左边的轮子
                g.fill3DRect(x + 13, y - 35, 14, 70, false);//坦克右边的轮子
                g.fill3DRect(x - 13, y - 20, 26, 40, false);//坦克主控室
                g.fillOval(x - 13, y - 13, 26, 26);//坦克炮头盖
                g.fillRect(x - 2, y, 4, 35);//坦克炮管
                break;
            case 2://方向为左
                g.fill3DRect(x - 35, y - 27, 70, 14, false);//坦克上边的轮子
                g.fill3DRect(x - 35, y + 13, 70, 14, false);//坦克下边的轮子
                g.fill3DRect(x - 20, y - 13, 40, 26, false);//坦克主控室
                g.fillOval(x - 13, y - 13, 26, 26);//坦克炮头盖
                g.fillRect(x - 35, y - 2, 35, 4);//坦克炮管
                break;
            case 3://方向为右
                g.fill3DRect(x - 35, y - 27, 70, 14, false);//坦克上边的轮子
                g.fill3DRect(x - 35, y + 13, 70, 14, false);//坦克下边的轮子
                g.fill3DRect(x - 20, y - 13, 40, 26, false);//坦克主控室
                g.fillOval(x - 13, y - 13, 26, 26);//坦克炮头盖
                g.fillRect(x, y - 2, 35, 4);//坦克炮管
                break;
            default:
                System.out.println("还未处理");
        }
    }

    //编写 hitTank()和hitEnemyTank()方法，用于判断我方的子弹是否击中敌方坦克
    public void hitTank(Shot s, Tank tank) {
        //判断 s 是否击中坦克
        switch (tank.getDirection()) {
            case 0://坦克向上
            case 1://坦克向下
                if (tank.isLive) {//先判断坦克是否存活
                    if (s.x > tank.getX() - 27 && s.x < tank.getX() + 27
                            && s.y > tank.getY() - 35 && s.y < tank.getY() + 35) {
                        s.isLive = false;
                        tank.isLive = false;
                        //把被击中的坦克从集合中删除
                        //remove() 方法会在集合中找出并删除指定元素，
                        //如果元素不存在，remove() 方法将不会对集合进行任何修改
                        //故无需用 contains 判断坦克属于哪个集合
                        enemyTanks.remove(tank);
                        heroTanks.remove(tank);
                        //创建Bomb对象加入到bombs集合
                        Bomb bomb = new Bomb(tank.getX() - 27, tank.getY() - 35);
                        bombs.add(bomb);
                        //在子弹击中坦克后立即重绘
                        this.repaint();
                    }
                    break;
                }
            case 2://坦克向左
            case 3://坦克向右
                if (tank.isLive) {
                    if (s.x > tank.getX() - 35 && s.x < tank.getX() + 35
                            && s.y > tank.getY() - 27 && s.y < tank.getY() + 27) {
                        s.isLive = false;
                        tank.isLive = false;
                        //把被击中的坦克从集合中删除
                        enemyTanks.remove(tank);
                        heroTanks.remove(tank);
                        //创建Bomb对象加入到bombs集合
                        Bomb bomb = new Bomb(tank.getX() - 35, tank.getY() - 27);
                        bombs.add(bomb);
                        //在子弹击中坦克后立即重绘
                        this.repaint();
                    }
                    break;
                }
        }
    }

    //判断我方坦克射击的子弹集合是否击中敌方坦克
    public void hitEnemyTank() {
        for (int i = 0; i < heroTanks.size(); i++) {
            HeroTank heroTank = heroTanks.get(i);
            for (int j = 0; j < heroTank.shots.size(); j++) {
                Shot shot = heroTank.shots.get(j);
                if (shot != null && shot.isLive) {//当自己的子弹还存活时
                    //遍历敌人所有的坦克
                    for (int k = 0; k < enemyTanks.size(); k++) {
                        EnemyTank enemyTank = enemyTanks.get(k);
                        hitTank(shot, enemyTank);
                    }
                }
            }
        }

    }

    //判断敌方射击的子弹集合是否击中我方坦克
    public void hitHeroTank() {
        for (int i = 0; i < enemyTanks.size(); i++) {
            //取出敌人坦克
            EnemyTank enemyTank = enemyTanks.get(i);
            //遍历敌方坦克所有的子弹
            for (int j = 0; j < enemyTank.shots.size(); j++) {
                //取出敌人的子弹
                Shot shot = enemyTank.shots.get(j);
                //判断 shot 是否击中我方坦克
                for (int k = 0; k < heroTanks.size(); k++) {
                    HeroTank heroTank = heroTanks.get(k);
                    if (heroTank.isLive && shot.isLive) {
                        hitTank(shot, heroTank);
                    }
                }
            }
        }

    }

    //有字符输出时，该方法就会触发
    @Override
    public void keyTyped(KeyEvent e) {

    }

    //处理wasd按下的情况
    //当某个键按下时，该方法就会触发
    @Override
    public void keyPressed(KeyEvent e) {
        for (int i = 0; i < heroTanks.size(); i++) {
            HeroTank heroTank = heroTanks.get(i);
            if (e.getKeyCode() == KeyEvent.VK_W) {//按下w键
                //改变坦克的方向
                heroTank.setDirection(0);
                heroTank.moveUp();
            } else if (e.getKeyCode() == KeyEvent.VK_S) {
                heroTank.setDirection(1);
                heroTank.moveDown();
            } else if (e.getKeyCode() == KeyEvent.VK_A) {
                heroTank.setDirection(2);
                heroTank.moveLeft();
            } else if (e.getKeyCode() == KeyEvent.VK_D) {
                heroTank.setDirection(3);
                heroTank.moveRight();
            }

            //如果用户按下 J 键，就发射子弹
            if (e.getKeyCode() == KeyEvent.VK_J) {
                heroTank.shotTank();
            }

            //让画板mp重绘
            this.repaint();
        }

    }

    //当某个键松开时，该方法就会触发
    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void run() {//每格20毫秒刷新面板区域
        while (true) {
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //调用方法，判断我方坦克射击的子弹集合是否击中敌方坦克
            hitEnemyTank();
            //调用方法，判断敌方坦克射击的子弹集合是否击中我方坦克
            hitHeroTank();
            this.repaint();
        }
    }

}
